import os.path
import time
from threading import Thread
from typing import Union, Callable

from scripts.Log import Log
from scripts.actions.Action import Action
from scripts.actions.Context import Context


class BackupAdbBackupAction(Action):
    KEY = Action.register('adb-backup')
    DISPLAY_NAME = 'Adb backup'
    HOST_FILE_NAME = 'all.backup'

    def __init__(self, context: Context):
        super().__init__(BackupAdbBackupAction.KEY, BackupAdbBackupAction.DISPLAY_NAME, context)
        self._host_file = os.path.join(self.data_dir(), BackupAdbBackupAction.HOST_FILE_NAME)

    def _on_backup(self, progress: Union[None, Callable[[int, int, str], None]]):
        device = self.wait_for_device()

        if progress:
            progress(0, 1, 'NOTE: DO NOT TOUCH SCREEN!!!')

        self._auto_accept()

        Log.i('=========================================================')
        Log.i('= DO NOT TOUCH SCREEN!!!                                =')
        Log.i('= Screen operation will be auto done to accept backup.  =')
        Log.i('=========================================================')
        device.backup(self._host_file, None)

        if progress:
            progress(1, 1, 'Done [%s]' % self.duration_time_str())

    def _on_restore(self, progress: Union[None, Callable[[int, int, str], None]]):
        device = self.wait_for_device()

        if progress:
            progress(0, 2, 'NOTE: DO NOT TOUCH SCREEN!!!')

        self._auto_accept()

        Log.i('=========================================================')
        Log.i('= DO NOT TOUCH SCREEN!!!                                =')
        Log.i('= Screen operation will be auto done to accept restore. =')
        Log.i('=========================================================')
        device.restore(self._host_file)

        if progress:
            progress(1, 1, 'Done [%s]' % self.duration_time_str())

    def _auto_accept(self):
        t = Thread(target=self._auto_accept_proc)
        t.start()

    def _auto_accept_proc(self):
        time.sleep(3)  # wait 1 second to wait for adb backup cmd ready

        device = self.wait_for_device()
        with device.shell() as shell:
            retry = 10
            win = shell.window_policy()
            while retry > 0 and (not win.screen_on or win.keyguard_showing):
                retry -= 1

                # turn on screen
                if not win.screen_on:
                    shell.input_keyevent('KEYCODE_POWER')
                    Log.d('Auto: turn screen on')

                    # next loop for check
                    time.sleep(1)
                    win = shell.window_policy()
                    continue

                # unlock keyguard
                if win.keyguard_showing:
                    shell.input_swipe(100, 800, 100, 100)
                    Log.d('Auto: unlock keyguard')

                    # next loop for check
                    time.sleep(1)
                    win = shell.window_policy()
                    continue

                Log.i('Device unlocked')

            if retry <= 0:
                Log.e('Cannot auto unlock screen!! '
                      'If screen pattern is set remove it and try again. Or manually accept.')
                return

            # press 530 1230
            shell.input_tap(530, 1230)
            Log.d('Auto: press button')
